﻿using Coway.Ordering.Buyers;
using Coway.Ordering.PayOrders;
using Coway.Ordering.Pdfs;
using Coway.Ordering.Sellers;
using Microsoft.AspNetCore.Http;
using System;
using System.IO;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.BlobStoring;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Security.Encryption;

namespace Coway.Ordering.Orders
{
    /// <summary>
    /// 订单的应用服务
    /// </summary>
    //[Authorize(BookStorePermissions.Books.Default)]
    public class OrderAppService : CrudAppService<
            Order, //The Book entity
            OrderDto, //Used to show books
            Guid, //Primary key of the book entity
            PagedAndSortedResultRequestDto, //Used for paging/sorting
            CreateUpdateOrderDto>, //Used to create/update a book
        IOrderAppService //implement the IBookAppService
    {
        //private readonly IAuthorRepository _authorRepository;
        private readonly INewOrderGenerator _newOrderGenerator;
        private readonly IRepository<Seller, string> _sellerGenerator;
        private readonly IRepository<Buyer, Guid> _buyerRepository;
        private readonly IRepository<ACHPayOrder, Guid> _achPayOrderRepository;
        private readonly IRepository<CCRPayOrder, Guid> _ccrPayOrderRepository;
        private readonly IRepository<InstallationInfo, Guid> _installRepository;
        private readonly IRepository<OrderItem, Guid> _orderItemRepository;
        private readonly IBlobContainer _blobContainer;
        private readonly IStringEncryptionService _stringEncryptionService;

        public OrderAppService(
            INewOrderGenerator newOrderGenerator,
            IRepository<Seller, string> sellerGenerator,
            IRepository<Buyer, Guid> buyerRepository,
            IRepository<ACHPayOrder, Guid> achPayOrderRepository,
            IRepository<CCRPayOrder, Guid> ccrPayOrderRepository,
            IRepository<InstallationInfo, Guid> installRepository,
            IRepository<OrderItem, Guid> orderItemRepository,
            IBlobContainer blobContainer,
            IStringEncryptionService stringEncryptionService,
            IRepository<Order, Guid> repository)
            : base(repository)
        {
            _newOrderGenerator = newOrderGenerator;
            _sellerGenerator = sellerGenerator;
            _buyerRepository = buyerRepository;
            _achPayOrderRepository = achPayOrderRepository;
            _ccrPayOrderRepository = ccrPayOrderRepository;
            _installRepository = installRepository;
            _blobContainer = blobContainer;
            _stringEncryptionService = stringEncryptionService;
            _orderItemRepository = orderItemRepository;
            //_authorRepository = authorRepository;
            //GetPolicyName = BookStorePermissions.Books.Default;
            //GetListPolicyName = BookStorePermissions.Books.Default;
            //CreatePolicyName = BookStorePermissions.Books.Create;
            //UpdatePolicyName = BookStorePermissions.Books.Edit;
            //DeletePolicyName = BookStorePermissions.Books.Create;
        }

        /// <summary>
        /// 获取指定销售代码的销售订单草稿
        /// </summary>
        /// <param name="sellerCode">销售代码</param>
        /// <returns></returns>
        public async Task<OrderDto> GetDraftSellOrderAsync(string sellerCode)
        {
            var seller = await _sellerGenerator.FindAsync(s => s.Code == sellerCode);
            if (seller == null)
            {
                throw new UserFriendlyException($"未找到相关销售人员信息({sellerCode})，请联系管理员。");
            }

            var draftOrder = new OrderDto { SellerName = seller.Name, SellerCode = seller.Code, SellerPhone = seller.Phone };
            return draftOrder;
        }

        public override async Task<OrderDto> GetAsync(Guid id)
        {
            var dto = await base.GetAsync(id);

            return dto;
        }

        /// <summary>
        /// 对应于：PlaceOrder ，下订单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public override async Task<OrderDto> CreateAsync(CreateUpdateOrderDto input)
        {
            var order = await _newOrderGenerator.GenerateAsync(input);
            await Repository.InsertAsync(order, autoSave: true);
            return await MapToGetOutputDtoAsync(order);
        }

        /// <summary>
        /// 客户提交信息对应于：PlaceOrder ，下订单
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<OrderDto> CreateByCustomerAsync(CustomerUpdateOrderDto input)
        {
            if (input.BillingSameAboveLegalAddress)
            {
                input.BillingAddressApt = input.LegalAddressApt;
                input.BillingAddressCity = input.LegalAddressCity;
                input.BillingAddressStreet = input.LegalAddressStreet;
                input.BillingAddressZipCode = input.LegalAddressZipCode;
                input.BillingAddressState = input.LegalAddressState;
            }

            if (input.InstallationSameAboveLegalAddress)
            {
                input.AddressApt = input.LegalAddressApt;
                input.AddressCity = input.LegalAddressCity;
                input.AddressStreet = input.LegalAddressStreet;
                input.AddressZipCode = input.LegalAddressZipCode;
                input.AddressState = input.LegalAddressState;
            }

            if (input.InstallationSameAboveName)
            {
                input.InstallationFirstName = input.FirstName;
                input.InstallationLastName = input.LastName;
            }

            var buyer = new Buyer
            {
                FirstName = input.FirstName,
                LastName = input.LastName,
                BillingAddressApt = input.BillingAddressApt,
                BillingAddressCity = input.BillingAddressCity,
                BillingAddressStreet = input.BillingAddressStreet,
                BillingAddressZipCode = input.BillingAddressZipCode,
                BillingAddressState = input.BillingAddressState,
                DateOfBirth = input.DateOfBirth,
                EMail = input.EMail,
                HomePhone = input.HomePhone,
                LegalAddressApt = input.LegalAddressApt,
                LegalAddressCity = input.LegalAddressCity,
                LegalAddressState = input.LegalAddressState,
                LegalAddressStreet = input.LegalAddressStreet,
                LegalAddressZipCode = input.LegalAddressZipCode,
                Mobile = input.Mobile,
                SocialSecurityNumber = _stringEncryptionService.Encrypt(input.SocialSecurityNumber),
                TaxId = input.TaxId,
            };
            await _buyerRepository.InsertAsync(buyer);

            var installationInfo = new InstallationInfo
            {
                AddressApt = input.AddressApt,
                AddressCity = input.AddressCity,
                AddressState = input.AddressState,
                AddressStreet = input.AddressStreet,
                AddressZipCode = input.AddressZipCode,

                FirstName = input.InstallationFirstName,
                LastName = input.InstallationLastName,

                RequestDate = input.RequestDate,
                Remarks = input.Remarks,
                Option = input.Option,
                HomePhone = input.InstallationHomePhone,
                Membership = input.Membership,
                Mobile = input.Mobile,
            };

            await _installRepository.InsertAsync(installationInfo);

            var order = await Repository.GetAsync(input.Id);
            order.BuyerId = buyer.Id;
            order.InstallationInfoId = installationInfo.Id;
            await Repository.UpdateAsync(order);

            return await MapToGetOutputDtoAsync(order);
        }

        /// <summary>
        /// 上传签名图片文件
        /// </summary>
        /// <returns></returns>
        public async Task<string> UploadSignatureImage(IFormFile file, Guid orderId)
        {
            var bytes = await file.GetAllBytesAsync();
            // 保留 7 天
            await _blobContainer.SaveAsync(file.FileName.Replace("image", Guid.NewGuid().ToString()), bytes, true);

            // 导出PDF
            var strOrderId = orderId.ToString();
            var ccrPayOrder = await _ccrPayOrderRepository.FirstOrDefaultAsync(p => p.OrderId == strOrderId);
            var achPayOrder = await _achPayOrderRepository.FirstOrDefaultAsync(p => p.OrderId == strOrderId);

            var pdfService = ServiceProvider.GetService(typeof(PdfAppService)) as PdfAppService;
            await pdfService.ExportOrder(orderId, achPayOrder, ccrPayOrder, bytes);

            return Convert.ToBase64String(bytes);
        }

        /// <summary>
        /// 上传付款信息（如支票）
        /// </summary>
        /// <returns></returns>
        public async Task<string> UploadPayImage(IFormFile file)
        {
            var newFileName = Guid.NewGuid() + Path.GetExtension(file.FileName);

            var bytes = await file.GetAllBytesAsync();
            // 保留 7 天
            await _blobContainer.SaveAsync(newFileName, bytes, true);

            return newFileName;
        }

        public async Task<bool> CreateACHPayOrder(CreateACHPayOrderDto input)
        {
            input.CardNo = _stringEncryptionService.Encrypt(input.CardNo);
            input.CVV = _stringEncryptionService.Encrypt(input.CVV);

            var order = await _achPayOrderRepository.FirstOrDefaultAsync(o => o.OrderId == input.OrderId);
            if (order != null)
            {
                var payOrder = ObjectMapper.Map<CreateACHPayOrderDto, ACHPayOrder>(input, order);
                await _achPayOrderRepository.UpdateAsync(payOrder);
            }
            else
            {
                var payOrder = ObjectMapper.Map<CreateACHPayOrderDto, ACHPayOrder>(input);
                await _achPayOrderRepository.InsertAsync(payOrder);
            }

            //var pdfService = ServiceProvider.GetService(typeof(PdfAppService)) as PdfAppService;
            //await pdfService.ExportOrder(new Guid(input.OrderId), payOrder, null);

            return true;
        }

        public async Task<bool> CreateCCRPayOrder(CreateCCRPayOrderDto input)
        {
            input.CardNo = _stringEncryptionService.Encrypt(input.CardNo);
            input.CVV = _stringEncryptionService.Encrypt(input.CVV);

            var order = await _ccrPayOrderRepository.FirstOrDefaultAsync(o => o.OrderId == input.OrderId);
            if (order != null)
            {
                var payOrder = ObjectMapper.Map<CreateCCRPayOrderDto, CCRPayOrder>(input, order);
                await _ccrPayOrderRepository.UpdateAsync(payOrder);
            }
            else
            {
                var payOrder = ObjectMapper.Map<CreateCCRPayOrderDto, CCRPayOrder>(input);
                await _ccrPayOrderRepository.InsertAsync(payOrder);
            }

            //var pdfService = ServiceProvider.GetService(typeof(PdfAppService)) as PdfAppService;
            //await pdfService.ExportOrder(new Guid(input.OrderId), null, payOrder);

            return true;
        }
    }
}
